<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-alpha.63">
<title data-react-helmet="true">5. 友好异常处理 | Fur</title><meta data-react-helmet="true" name="docsearch:version" content="current,latest"><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:title" content="5. 友好异常处理 | Fur"><meta data-react-helmet="true" name="description" content="5.1 什么是异常"><meta data-react-helmet="true" property="og:description" content="5.1 什么是异常"><meta data-react-helmet="true" property="og:url" content="https://furos.cn/docs/friendly-exception"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://furos.cn/docs/friendly-exception"><link rel="stylesheet" href="/styles.83aacb78.css">
<link rel="preload" href="/styles.16c5981f.js" as="script">
<link rel="preload" href="/runtime~main.017debba.js" as="script">
<link rel="preload" href="/main.b54c8f62.js" as="script">
<link rel="preload" href="/1.0b36cbc2.js" as="script">
<link rel="preload" href="/2.17909aba.js" as="script">
<link rel="preload" href="/3.f42eda22.js" as="script">
<link rel="preload" href="/1be78505.c23a6c85.js" as="script">
<link rel="preload" href="/31.92e96840.js" as="script">
<link rel="preload" href="/f976f453.bd53d64a.js" as="script">
<link rel="preload" href="/17896441.c3d5fc96.js" as="script">
<link rel="preload" href="/62953dcd.f2fc3c60.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<nav class="navbar navbar--light navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><div aria-label="Navigation bar toggle" class="navbar__toggle" role="button" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></div><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs/">Next</a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs">文档</a><a class="navbar__item navbar__link" href="/blog">博客</a><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">配置</a></div><div class="navbar__items navbar__items--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">视频</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">工具</a><ul class="dropdown__menu"><li><a target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">代码生成器</a></li></ul></div><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">看板</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">仓库</a><ul class="dropdown__menu"><li><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">Gitee</a></li><li><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">GitHub</a></li></ul></div><div class="react-toggle react-toggle--disabled displayOnlyInLargeViewport_2aTZ"><div class="react-toggle-track"><div class="react-toggle-track-check"><span class="toggle_BsTx">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_BsTx">🌞</span></div></div><div class="react-toggle-thumb"></div><input type="checkbox" disabled="" aria-label="Dark mode toggle" class="react-toggle-screenreader-only"></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div><div class="navbar-sidebar"><div class="navbar-sidebar__brand"><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a></div><div class="navbar-sidebar__items"><div class="menu"><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">Versions</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link navbar__link--active" href="/docs">文档</a></li><li class="menu__list-item"><a class="menu__link" href="/blog">博客</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">配置</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">视频</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">工具</a><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link" position="left">代码生成器</a></li></ul></li><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="menu__link">看板</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">仓库</a><ul class="menu__list"><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">Gitee</a></li><li class="menu__list-item"><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">GitHub</a></li></ul></li></ul></div></div></div></nav><div class="main-wrapper"><div class="docPage_2gpo"><div class="docSidebarContainer_3_JD" role="complementary"><div class="sidebar_2urC"><div class="menu menu--responsive menu_5FrY"><button aria-label="Open Menu" aria-haspopup="true" class="button button--secondary button--sm menu__button" type="button"><svg aria-label="Menu" class="sidebarMenuIcon_Dm3K" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 32 32" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ul class="menu__list"><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">1. 框架介绍</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/">1.1 介绍</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/author">1.2 关于作者</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">2. 配置与选项</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/configuration">2.1 配置</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/options">2.2 选项</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/dynamic-api-controller">3. 动态 WebAPI</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/specification-document">4. 规范化接口文档</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active active" href="/docs/friendly-exception">5. 友好异常处理</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/data-validation">6. 数据校验</a></li></ul></div></div></div><main class="docMainContainer_3EyW"><div class="container padding-vert--lg docItemWrapper_1EkI"><div class="row"><div class="col docItemCol_2ASc"><div class="docItemContainer_3QWW"><article><header><h1 class="docTitle_1Lrw">5. 友好异常处理</h1></header><div class="markdown"><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="51-什么是异常"></a>5.1 什么是异常<a aria-hidden="true" tabindex="-1" class="hash-link" href="#51-什么是异常" title="Direct link to heading">#</a></h2><p>异常一般是指运行期（此处特指 <code>Exception</code> 类）会发生的导致程序意外中止的问题，是一种对问题的描述后的封装对象。</p><p>在过去开发中，通常异常由系统运行时出错抛出，但现在的开发过程中，我们应在程序开发中合理的抛出异常，比如更新一条不存在的实体，或查询一个不存在的数据等等。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="52-处理异常方式"></a>5.2 处理异常方式<a aria-hidden="true" tabindex="-1" class="hash-link" href="#52-处理异常方式" title="Direct link to heading">#</a></h2><ul><li>不处理，直接中断程序执行（不推荐）</li><li>通过 <code>try catch finally</code> 处理（不推荐）</li><li>全局统一处理，并记录异常信息<strong>（推荐）</strong></li><li>异常注解方式处理，支持<strong>本地化</strong> <strong>（推荐）</strong></li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="53-什么是友好异常处理"></a>5.3 什么是友好异常处理<a aria-hidden="true" tabindex="-1" class="hash-link" href="#53-什么是友好异常处理" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="531-非友好异常处理"></a>5.3.1 非友好异常处理<a aria-hidden="true" tabindex="-1" class="hash-link" href="#531-非友好异常处理" title="Direct link to heading">#</a></h3><p>在了解友好异常处理之前可以看看非友好异常处理：</p><ul><li>对终端用户抛出 <code>500状态码</code> 堆栈信息</li><li>大量的 <code>try catch</code> 代码，污染正常业务逻辑</li><li>没有规范化的异常状态码和异常消息管理</li><li>没有异常日志收集记录</li><li>不支持异常消息本地化处理</li><li>不支持异常策略，失败后程序立即终止</li><li>不支持分布式事务 CAP</li><li>不支持异常传播</li><li>返回的异常格式杂乱</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="532-友好异常处理"></a>5.3.2 友好异常处理<a aria-hidden="true" tabindex="-1" class="hash-link" href="#532-友好异常处理" title="Direct link to heading">#</a></h3><ul><li>对终端用户提示友好</li><li>对后端开发人员提供详细的异常堆栈</li><li>不干扰正常业务逻辑代码，如 没有 <code>try catch</code> 代码</li><li>支持异常状态码多方设置</li><li>支持异常消息本地化</li><li>异常信息统一配置管理</li><li>支持异常策略，如重试</li><li>支持异常日志收集记录</li><li>支持 CAP 分布式事务关联</li><li>支持内部异常外部传播</li><li>支持返回统一的异常格式数据</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="54-友好异常处理使用示例"></a>5.4 友好异常处理使用示例<a aria-hidden="true" tabindex="-1" class="hash-link" href="#54-友好异常处理使用示例" title="Direct link to heading">#</a></h2><p><code>Fur</code> 框架提供了非常灵活的友好异常处理方式。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="541-注册友好异常服务"></a>5.4.1 注册友好异常服务<a aria-hidden="true" tabindex="-1" class="hash-link" href="#541-注册友好异常服务" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div style="color:#bfc7d5;background-color:#292d3e" class="codeBlockTitle_3nn1">Fur.Web.Entry/Startup.cs</div><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd undefined">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC codeBlockWithTitle_3QsD"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Builder;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Hosting;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.Extensions.DependencyInjection;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Entry</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class Startup</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void ConfigureServices(IServiceCollection services)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            services.AddApp();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            services.AddControllers()</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                    .AddFriendlyException();    // 可通过 .AddFriendlyException(false) 关闭全局异常处理</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>.AddFriendlyException()</code> 需在 <code>services.AddControllers()</code> 之后注册。同时 <code>services.AddApp()</code> 总是最先注册。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="542-两个例子"></a>5.4.2 两个例子<a aria-hidden="true" tabindex="-1" class="hash-link" href="#542-两个例子" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="简单抛个异常"></a>简单抛个异常<a aria-hidden="true" tabindex="-1" class="hash-link" href="#简单抛个异常" title="Direct link to heading">#</a></h4><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh($&quot;{id} 不能小于3&quot;);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/yhyc1.gif"><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="抛出特定类型异常"></a>抛出特定类型异常<a aria-hidden="true" tabindex="-1" class="hash-link" href="#抛出特定类型异常" title="Direct link to heading">#</a></h4><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using System;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh($&quot;{id} 不能小于3。&quot;, typeof(InvalidOperationException));</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/yhyc2.png"><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="55-关于-oopsoh"></a>5.5 关于 Oops.Oh<a aria-hidden="true" tabindex="-1" class="hash-link" href="#55-关于-oopsoh" title="Direct link to heading">#</a></h2><p>通过上面的例子可以看出，<code>Oops.Oh(errorMessage)</code> 可以结合 <code>throw</code> 抛出异常。对于熟悉<code>C#</code>的人员来说，<code>throw</code> 后面只能 <code>Exception</code> 实例。<code>Oops.Oh(...)</code> 方法返回正是 <code>Exception</code> 实例。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="551-为什么起这个名字？"></a>5.5.1 为什么起这个名字？<a aria-hidden="true" tabindex="-1" class="hash-link" href="#551-为什么起这个名字？" title="Direct link to heading">#</a></h3><p>这个名字来源于一个英语句子：<code>Oh, Oops!</code>，意思是 <strong>噢（哎），出错了！</strong>，所以就有了 <code>Oops.Oh</code>。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="552-oopsoh-重载方法"></a>5.5.2 <code>Oops.Oh</code> 重载方法<a aria-hidden="true" tabindex="-1" class="hash-link" href="#552-oopsoh-重载方法" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using System;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.FriendlyException</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public static class Oops</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 抛出字符串异常</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;errorMessage&quot;&gt;异常消息&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;args&quot;&gt;String.Format 参数&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;异常实例&lt;/returns&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public static Exception Oh(string errorMessage, params object[] args);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 抛出字符串异常</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;errorMessage&quot;&gt;异常消息&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;exceptionType&quot;&gt;具体异常类型&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;args&quot;&gt;String.Format 参数&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;异常实例&lt;/returns&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 抛出错误码异常</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;errorCode&quot;&gt;错误码&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;args&quot;&gt;String.Format 参数&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;异常实例&lt;/returns&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public static Exception Oh(object errorCode, params object[] args);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// 抛出错误码异常</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;/summary&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;errorCode&quot;&gt;错误码&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;exceptionType&quot;&gt;具体异常类型&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;param name=&quot;args&quot;&gt;String.Format 参数&lt;/param&gt;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        /// &lt;returns&gt;异常实例&lt;/returns&gt;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public static Exception Oh(object errorCode, Type exceptionType, params object[] args);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="56-最佳实践-"></a>5.6 最佳实践 🤗<a aria-hidden="true" tabindex="-1" class="hash-link" href="#56-最佳实践-" title="Direct link to heading">#</a></h2><p>在 <code>Fur</code> 框架中，提供了非常灵活且规范化的友好异常处理方式，通过这个方式可以方便管理异常状态码、异常信息及异常本地化。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="561-创建异常信息类型"></a>5.6.1 创建异常信息类型<a aria-hidden="true" tabindex="-1" class="hash-link" href="#561-创建异常信息类型" title="Direct link to heading">#</a></h3><p>实现自定义异常信息类型必须遵循以下配置：</p><ul><li>类型必须是公开且时 <code>Enum</code> 枚举类型</li><li>枚举类型必须贴有 <code>[ErrorCodeType]</code> 特性</li><li>枚举中每一项必须贴有 <code>[ErrorCodeItemMetadata]</code> 特性</li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ErrorCodeType]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public enum ErrorCodes</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;{0} 不能小于 {1}&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        z1000,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;数据不存在&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        x1000,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;{0} 发现 {1} 个异常&quot;, &quot;百小僧&quot;, 2)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        x1001,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;服务器运行异常&quot;, ErrorCode = &quot;Error&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        SERVER_ERROR</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>important</h5></div><div class="admonition-content"><p><code>Fur</code> 框架提供了 <code>[ErrorCodeType]</code> 特性和 <code>IErrorCodeTypeProvider</code> 提供器接口来提供异常信息扫描，这里用的是 <code>[ErrorCodeType]</code> 特性类。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="562-关于-errorcodeitemmetadata"></a>5.6.2 关于 <code>[ErrorCodeItemMetadata]</code><a aria-hidden="true" tabindex="-1" class="hash-link" href="#562-关于-errorcodeitemmetadata" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架提供了<code>[ErrorCodeItemMetadata]</code> 特性用来标识<strong>枚举字段</strong>异常元数据，该特性支持传入 <code>消息内容</code> 和 <code>格式化参数</code>。最终会使用 <code>String.Format(消息内容，格式化参数)</code> 进行格式化。</p><p>如果消息内容中包含<code>格式化占位符</code>但未指定<code>格式化参数</code>，那么会查找异常所在方法是否贴有 <code>[IfException]</code> 特性且含有格式化参数，接着就会查找 <code>Oops.Oh</code> 中指定的 <code>格式化参数</code>。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="563-静态异常类使用"></a>5.6.3 静态异常类使用<a aria-hidden="true" tabindex="-1" class="hash-link" href="#563-静态异常类使用" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh(ErrorCodes.z1000, id, 3);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/yhyc3.gif"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="564-更多例子"></a>5.6.4 更多例子<a aria-hidden="true" tabindex="-1" class="hash-link" href="#564-更多例子" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">throw Oops.Oh(1000);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">throw Oops.Oh(ErrorCodes.x1000);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">throw Oops.Oh(&quot;哈哈哈哈&quot;);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">throw Oops.Oh(errorCode: &quot;x1001&quot;);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">throw Oops.Oh(1000, typeof(Exception));</span></div></div></div></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="57-多个异常信息类型"></a>5.7 多个异常信息类型<a aria-hidden="true" tabindex="-1" class="hash-link" href="#57-多个异常信息类型" title="Direct link to heading">#</a></h2><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ErrorCodeType]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public enum ErrorCodes</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;{0} 不能小于 {1}&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        z1000,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;数据不存在&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        x1000,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;{0} 发现 {1} 个异常&quot;, &quot;百小僧&quot;, 2)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        x1001,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;服务器运行异常&quot;, ErrorCode = &quot;Error&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        SERVER_ERROR</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ErrorCodeType]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public enum UserErrorCodes</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;用户数据不存在&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        u1000,</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        [ErrorCodeItemMetadata(&quot;其他异常&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        u1001</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p>多个异常静态类中也必须保证常量值唯一性，不可重复。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="58-ierrorcodetypeprovider-提供器"></a>5.8 <code>IErrorCodeTypeProvider</code> 提供器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#58-ierrorcodetypeprovider-提供器" title="Direct link to heading">#</a></h2><p>在 <code>Fur</code> 框架中，还提供了 <code>IErrorCodeTypeProvider</code> 异常消息提供器接口，方便在不能贴 <code>[ErrorCodeType]</code> 特性情况下使用：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using System;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public Type[] Definitions =&gt; new[] {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            typeof(ErrorCodes),</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            typeof(ErrorCodes2)</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        };</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>使用 <code>IErrorCodeTypeProvider</code> 方式需要在 <code>Startup.cs</code> 中注册：</p><div class="mdxCodeBlock_1XEh"><div style="color:#bfc7d5;background-color:#292d3e" class="codeBlockTitle_3nn1">Fur.Web.Entry/Startup.cs</div><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd undefined">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC codeBlockWithTitle_3QsD"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Builder;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Hosting;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.Extensions.DependencyInjection;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Entry</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class Startup</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void ConfigureServices(IServiceCollection services)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            services.AddApp();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            services.AddControllers()</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                    .AddFriendlyException&lt;CustomErrorCodeTypeProvider&gt;();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小知识</h5></div><div class="admonition-content"><p>只有使用 <code>IErrorCodeTypeProvider</code> 方式才需使用泛型方式注册。通过上面的方式注册可以同时支持 <code>IErrorCodeTypeProvider</code> 和 <code>[ErrorCodeType]</code> 方式。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="59-appsettingjson-中配置"></a>5.9 <code>appsetting.json</code> 中配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#59-appsettingjson-中配置" title="Direct link to heading">#</a></h2><p><code>Fur</code> 框架还提供了非常灵活的配置文件配置异常，通过这种方式可以实现异常信息后期配置，也就是无需在开发阶段预先定义。</p><div class="mdxCodeBlock_1XEh"><div style="color:#bfc7d5;background-color:#292d3e" class="codeBlockTitle_3nn1">Fur.Web.Entry/appsettings.json</div><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd undefined">Copy</button><div tabindex="0" class="prism-code language-json codeBlock_3iAC codeBlockWithTitle_3QsD"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">&quot;AppSettings&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">&quot;ErrorCodeMessageSettings&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token property">&quot;Definitions&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">5000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">&quot;{0} 不能小于 {1}&quot;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">5001</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">&quot;我叫 {0} 名字&quot;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">&quot;百小僧&quot;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token number" style="color:rgb(247, 140, 108)">5002</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">&quot;Oops! 出错了&quot;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span></div></div></div></div></div><p><code>Definitions</code> 类型为二维数组，二维数组中的每一个数组第一个参数为 <code>ErrorCode</code> 也就是错误码，第二个参数为 <code>ErrorMessage</code> 消息内容，剩余参数作为 <code>ErrorMessage</code> 的格式化参数。</p><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="使用示例"></a>使用示例<a aria-hidden="true" tabindex="-1" class="hash-link" href="#使用示例" title="Direct link to heading">#</a></h4><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh(5000, id, 3); // 可以将 5000作为常量配置起来</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小知识</h5></div><div class="admonition-content"><p><code>[ErrorCodeType]</code> 和 <code>IErrorCodeTypeProvider</code> 和 <code>appsettings.json</code> 可以同时使用。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="510-ifexception-使用"></a>5.10 <code>[IfException]</code> 使用<a aria-hidden="true" tabindex="-1" class="hash-link" href="#510-ifexception-使用" title="Direct link to heading">#</a></h2><p><code>Fur</code> 框架提供了 <code>[IfException]</code> 特性可以<strong>覆盖默认消息配置</strong>。也就是覆盖 <code>异常消息类型</code> 和 <code>appsettings.json</code> 中的配置。</p><div class="admonition admonition-caution alert alert--warning"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>[IfException]</code> 只能贴在方法上，支持多个，而且该方法所在的类类型必须是 <code>ControllerBase</code> 子类 或 实现 <code>IDynamicApiController</code> 接口。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="5101-使用示例"></a>5.10.1 使用示例<a aria-hidden="true" tabindex="-1" class="hash-link" href="#5101-使用示例" title="Direct link to heading">#</a></h3><ul><li>异常消息类定义</li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">[ErrorCodeType]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">public static class ErrorCodes</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">   [ErrorCodeItemMetadata(&quot;{0} 不能小于 {1}&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">   z1000</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><ul><li>覆盖默认配置</li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [IfException(ErrorCodes.z1000, ErrorMessage = &quot;我覆盖了默认的：{0} 不能小于 {1}&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh(ErrorCodes.z1000, id, 3);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/yhyc4.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="5102-更多例子"></a>5.10.2 更多例子<a aria-hidden="true" tabindex="-1" class="hash-link" href="#5102-更多例子" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.FriendlyException;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [IfException(ErrorCodes.z1000, ErrorMessage = &quot;我覆盖了默认的：{0} 不能小于 {1}&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [IfException(ErrorCodes.x1001, &quot;格式化参数1&quot;, &quot;格式化参数2&quot;, ErrorMessage = &quot;我覆盖了默认的：{0} 不能小于 {1}&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [IfException(ErrorCodes.x1000, &quot;格式化参数1&quot;, &quot;格式化参数2&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [IfException(ErrorCodes.SERVER_ERROR, &quot;格式化参数1&quot;, &quot;格式化参数2&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            if (id &lt; 3)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">                throw Oops.Oh(ErrorCodes.z1000, id, 3);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>格式化流程</h5></div><div class="admonition-content"><p>如果消息内容中包含<code>格式化占位符</code>但未指定<code>格式化参数</code>，那么会查找异常所在方法是否贴有 <code>[IfException]</code> 特性且含有格式化参数，接着就会查找 <code>Oops.Oh</code> 中指定的 <code>格式化参数</code>。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="511-异常消息优先级"></a>5.11 异常消息优先级<a aria-hidden="true" tabindex="-1" class="hash-link" href="#511-异常消息优先级" title="Direct link to heading">#</a></h2><p><code>[ErrorCodeItemMetadata]</code> -&gt; <code>appsettings.json</code> -&gt; <code>[IfException]</code>。<strong>（低 -&gt; 高）</strong></p><ul><li><code>[IfException]</code> 会覆盖 <code>appsettings.json</code> 定义的状态码消息。</li><li><code>appsettings.json</code> 会覆盖 <code>[ErrorCodeItemMetadata]</code> 定义的消息。</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="512-多语言支持"></a>5.12 多语言支持<a aria-hidden="true" tabindex="-1" class="hash-link" href="#512-多语言支持" title="Direct link to heading">#</a></h2><p>文档整理中...</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="513-异常模型提供器"></a>5.13 异常模型提供器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#513-异常模型提供器" title="Direct link to heading">#</a></h2><p>文档整理中...</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="514-fur-内置异常"></a>5.14 <code>Fur</code> 内置异常<a aria-hidden="true" tabindex="-1" class="hash-link" href="#514-fur-内置异常" title="Direct link to heading">#</a></h2><ul><li><code>EFCoreErrorCodes</code>：<code>EF Core</code> 操作异常<ul><li><code>DataNotFound</code>：未找到数据</li><li><code>KeyNotSet</code>：没有设置主键</li></ul></li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="515-反馈与建议"></a>5.15 反馈与建议<a aria-hidden="true" tabindex="-1" class="hash-link" href="#515-反馈与建议" title="Direct link to heading">#</a></h2><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>与我们交流</h5></div><div class="admonition-content"><p>给 Fur 提 <a href="https://gitee.com/monksoul/Fur/issues/new?issue" target="_blank" rel="noopener noreferrer">Issue</a>。</p></div></div></div></article><div class="margin-vert--xl"><div class="row"><div class="col"><a href="https://gitee.com/monksoul/Fur/tree/alpha/docs/docs/friendly-exception.mdx" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="1.2em" width="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 40 40" style="margin-right:0.3em;vertical-align:sub"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div></div></div><div class="margin-vert--lg"><nav class="pagination-nav" aria-label="Blog list page navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/specification-document"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 4. 规范化接口文档</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/data-validation"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">6. 数据校验 »</div></a></div></nav></div></div></div><div class="col col--3"><div class="tableOfContents_3SO_"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#51-什么是异常" class="table-of-contents__link">5.1 什么是异常</a></li><li><a href="#52-处理异常方式" class="table-of-contents__link">5.2 处理异常方式</a></li><li><a href="#53-什么是友好异常处理" class="table-of-contents__link">5.3 什么是友好异常处理</a><ul><li><a href="#531-非友好异常处理" class="table-of-contents__link">5.3.1 非友好异常处理</a></li><li><a href="#532-友好异常处理" class="table-of-contents__link">5.3.2 友好异常处理</a></li></ul></li><li><a href="#54-友好异常处理使用示例" class="table-of-contents__link">5.4 友好异常处理使用示例</a><ul><li><a href="#541-注册友好异常服务" class="table-of-contents__link">5.4.1 注册友好异常服务</a></li><li><a href="#542-两个例子" class="table-of-contents__link">5.4.2 两个例子</a></li></ul></li><li><a href="#55-关于-oopsoh" class="table-of-contents__link">5.5 关于 Oops.Oh</a><ul><li><a href="#551-为什么起这个名字？" class="table-of-contents__link">5.5.1 为什么起这个名字？</a></li><li><a href="#552-oopsoh-重载方法" class="table-of-contents__link">5.5.2 <code>Oops.Oh</code> 重载方法</a></li></ul></li><li><a href="#56-最佳实践-" class="table-of-contents__link">5.6 最佳实践 🤗</a><ul><li><a href="#561-创建异常信息类型" class="table-of-contents__link">5.6.1 创建异常信息类型</a></li><li><a href="#562-关于-errorcodeitemmetadata" class="table-of-contents__link">5.6.2 关于 <code>[ErrorCodeItemMetadata]</code></a></li><li><a href="#563-静态异常类使用" class="table-of-contents__link">5.6.3 静态异常类使用</a></li><li><a href="#564-更多例子" class="table-of-contents__link">5.6.4 更多例子</a></li></ul></li><li><a href="#57-多个异常信息类型" class="table-of-contents__link">5.7 多个异常信息类型</a></li><li><a href="#58-ierrorcodetypeprovider-提供器" class="table-of-contents__link">5.8 <code>IErrorCodeTypeProvider</code> 提供器</a></li><li><a href="#59-appsettingjson-中配置" class="table-of-contents__link">5.9 <code>appsetting.json</code> 中配置</a></li><li><a href="#510-ifexception-使用" class="table-of-contents__link">5.10 <code>[IfException]</code> 使用</a><ul><li><a href="#5101-使用示例" class="table-of-contents__link">5.10.1 使用示例</a></li><li><a href="#5102-更多例子" class="table-of-contents__link">5.10.2 更多例子</a></li></ul></li><li><a href="#511-异常消息优先级" class="table-of-contents__link">5.11 异常消息优先级</a></li><li><a href="#512-多语言支持" class="table-of-contents__link">5.12 多语言支持</a></li><li><a href="#513-异常模型提供器" class="table-of-contents__link">5.13 异常模型提供器</a></li><li><a href="#514-fur-内置异常" class="table-of-contents__link">5.14 <code>Fur</code> 内置异常</a></li><li><a href="#515-反馈与建议" class="table-of-contents__link">5.15 反馈与建议</a></li></ul></div></div></div></div></main></div></div><footer class="footer footer--dark"><div class="container"><div class="row footer__links"><div class="col footer__col"><h4 class="footer__title">文档</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs">入门</a></li><li class="footer__item"><a class="footer__link-item" href="/docs">指南</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">社区</h4><ul class="footer__items"><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/issues" target="_blank" rel="noopener noreferrer" class="footer__link-item">讨论</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="footer__link-item">看板</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">更多</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/blog">博客</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="footer__link-item">仓库</a></li></ul></div></div><div class="text--center"><div>Copyright © 2020 Fur, Baiqian Co.,Ltd.</div></div></div></footer></div>
<script src="/styles.16c5981f.js"></script>
<script src="/runtime~main.017debba.js"></script>
<script src="/main.b54c8f62.js"></script>
<script src="/1.0b36cbc2.js"></script>
<script src="/2.17909aba.js"></script>
<script src="/3.f42eda22.js"></script>
<script src="/1be78505.c23a6c85.js"></script>
<script src="/31.92e96840.js"></script>
<script src="/f976f453.bd53d64a.js"></script>
<script src="/17896441.c3d5fc96.js"></script>
<script src="/62953dcd.f2fc3c60.js"></script>
</body>
</html>